package word;

import java.util.List;

import org.apache.poi.ooxml.POIXMLDocumentPart;
import org.apache.poi.xwpf.usermodel.XWPFDocument;
import org.apache.poi.xwpf.usermodel.XWPFParagraph;
import org.apache.poi.xwpf.usermodel.XWPFPicture;
import org.apache.poi.xwpf.usermodel.XWPFPictureData;
import org.apache.poi.xwpf.usermodel.XWPFRun;

/**
 * 转换 Word files(2007) .docx 到 HTML
 */
public class DocxToHtmlConverter {

  private DocxPicturesManager picturesManager;
  private String htmlStr;

  private class CssStyle {

    String cssStyle;

    public CssStyle(XWPFRun run) {
      StringBuilder style = new StringBuilder("");
      // if (isNotEmpty(run.getColor())) {
      //   style.append("color:#" + run.getColor() + ";");
      // }
      // if (run.getFontSizeAsDouble() != null) {
      //   style.append("font-size:" + run.getFontSizeAsDouble() + "pt;");
      // }
      if (run.isBold()) {
        style.append("font-weight:bold;");
      }
      if (run.isItalic()) {
        style.append("font-style:italic;");
      }
      if (run.isStrikeThrough() || run.isDoubleStrikeThrough()) {
        style.append("text-decoration:line-through;");
      }
      int verticalAlign = run.getVerticalAlignment().intValue();
      if (verticalAlign == 2) {
        style.append("vertical-align:super;");
      } else if (verticalAlign == 3) {
        style.append("vertical-align:sub;");
      }
      int underline = run.getUnderline().getValue();
      String underlineColor = run.getUnderlineColor();
      if (underlineColor == "auto") {
        underlineColor = "#000";
      }
      switch (underline) {
        case 1:
        case 2:
        case 15:
          style.append("border-bottom: 1px solid " + underlineColor + ";");
          break;
        case 3:
        case 17:
          style.append("border-bottom: 1px double " + underlineColor + ";");
          break;
        case 4:
        case 16:
          style.append("border-bottom: 2px solid " + underlineColor + ";");
          break;
        case 5:
          style.append("border-bottom: 1px dotted " + underlineColor + ";");
          break;
        case 6:
          style.append("border-bottom: 2px dotted " + underlineColor + ";");
          break;
        case 7:
        case 9:
        case 11:
        case 13:
          style.append("border-bottom: 1px dashed " + underlineColor + ";");
          break;
        case 8:
        case 10:
        case 12:
        case 14:
          style.append("border-bottom: 2px dashed " + underlineColor + ";");
          break;
        default:
          break;
      }
      cssStyle = style.toString();
    }

    public String getStyle() {
      return cssStyle;
    }
  }

  public void setPicturesManager(DocxPicturesManager picturesManager) {
    this.picturesManager = picturesManager;
  }

  public DocxPicturesManager getPicturesManager() {
    return this.picturesManager;
  }

  boolean isEmpty(String str) {
    return str == null || str.length() == 0;
  }

  boolean isNotEmpty(String str) {
    return !isEmpty(str);
  }

  
  public void processDocument(XWPFDocument document) {
    StringBuilder builder = new StringBuilder();
    // 解析文档的所有段落
    List<XWPFParagraph> ps = document.getParagraphs();
    for (int i = 0; i < ps.size(); i++) {
      XWPFParagraph p = ps.get(i);
      
      // 遍历段落里的所有节点
      List<XWPFRun> runs = p.getRuns();
      System.out.println(runs.size());
      StringBuilder inner = new StringBuilder();

      CssStyle style = null;
      String span = "";

      for (int j = 0; j < runs.size(); j++) {
        XWPFRun run = runs.get(j); // 段落里的每一个节点
        List<XWPFPicture> pictures = run.getEmbeddedPictures();
        if (pictures.size() == 0) { // 文本节点
          CssStyle thisStyle = new CssStyle(run);
          String thisText = "";
          String runText = run.getText(run.getTextPosition());
          if (j == 0) { // 换行后的 tab 是通过 left 来的
            int indentLeft = p.getIndentationLeft();
            int firstIndent = p.getIndentationFirstLine();
            if (firstIndent != -1) {
              int x = 0;
              if (indentLeft == -1) {
                x = 1;
              } else {
                x = (int) Math.floor(indentLeft / firstIndent);
                x++;
              }
              for (int k = 0; k < x; k++) {
                thisText += "&nbsp;&nbsp;&nbsp;&nbsp;";
              }
            }
          }
          if (runText != null) {
            // 插入tab
            int tabSize = run.getCTR().getTabList().size();
            if (tabSize > 0) {
              for (int k = 0; k < tabSize; k++) {
                thisText += "&nbsp;&nbsp;&nbsp;&nbsp;";
              }
            }
            thisText += runText;
            // 替换 HTML 特殊字符
			      thisText = thisText.replaceAll(" ", "&nbsp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;");
          }
          if (style == null) {
            style = thisStyle;
            span = thisText;
          } else if (thisStyle.getStyle().equals(style.getStyle())) {
            // 两次文本节点样式一样，则重置文本节点内容
            span += thisText;
          } else { // 两次文本节点样式不一样，保存上一次的文本节点
            inner.append(createSpan(span, style));
            style = thisStyle;
            span = thisText;
          }
        } else { // 图片节点
          // 保存上一个文本节点的内容
          if (style != null) {
            inner.append(createSpan(span, style));
            style = null;
            span = "";
          }
          for (int k = 0; k < pictures.size(); k++) {
            XWPFPicture picture = pictures.get(k);
            XWPFPictureData pdata = picture.getPictureData();
            DocxPictureType pictureType = new DocxPictureType(pdata.getPictureType());
            double width = picture.getWidth();
            double height = picture.getDepth();
            String ctyle = "width:" + width + "pt;height:" + height + "pt;";
            String src = picturesManager.savePictures(pdata.getData(), pictureType, pdata.getFileName(), pdata.suggestFileExtension(), picture.getWidth(), picture.getDepth());
            inner.append("<img style=\"" + ctyle + "\" src=\"" + src + "\">");
          }
        }
      }
      if (isNotEmpty(span)) {
        inner.append(createSpan(span, style));
      }
      builder.append("<p>" + inner.toString() + "</p>");
    }
    htmlStr = builder.toString();
  }

  private String createSpan(String text, CssStyle s) {
    if (!s.getStyle().equals("")) {
      return "<span style=\"" + s.getStyle() + "\">" + text + "</span>";
    } else {
      return "<span>" + text + "</span>";
    }
  }

  public String getHtmlString() {
    return htmlStr;
  }
}
